/* 实现一个通用的数组类-Vector：

* 可以对内置数据类型以及自定义数据类型的数据进行存储
* 将数组中的数据存储到堆区
* 构造函数中可以传入数组的容量
* 提供对应的拷贝构造函数以及operator=防止浅拷贝问题
* 提供尾插法和尾删法对数组中的数据进行增加和删除
* 可以通过下标的方式访问数组中的元素
* 可以获取数组中当前元素个数和数组的容量
* 可以判断数组是否为空 */

#include <iostream>
#include <string>

using namespace std;

template <class T>
class myArray
{
public:
    myArray();
    myArray(int capacity, int size = 0)
    {
        this->_capacity = capacity;
        this->_size = size;
        _pArray = new T[this->_capacity];
    }
    myArray(const myArray &Arr) // copy constructor
    {
        this->_capacity = Arr._capacity;
        this->_size = Arr._size;
        this->_pArray = new T[this->_capacity];

        for (size_t i = 0; i < _size; i++)
        {
            this->_pArray[i] = Arr._pArray[i];
        }
    }
    myArray &operator=(const myArray &Arr)
    {
        if (_pArray != nullptr)
        {
            delete[] _pArray;
            _size = 0;
            _capacity = 0;
        }

        _size = Arr._size;
        _capacity = Arr._capacity;
        _pArray = new T[_capacity];
        for (size_t i = 0; i < _size; i++)
        {
            _pArray[i] = Arr._pArray[i];
        }

        return *this;
    }
    void push_back(const T &tm)
    {
        if (_size == _capacity)
        {
            int newCapacity = _capacity + 10;
            T *newPArray = new T[newCapacity];
            if (_pArray != nullptr)
            {
                for (size_t i = 0; i < _size; i++)
                {
                    newPArray[i] = _pArray[i];
                }
            }
            delete[] _pArray;
            _pArray = newPArray;
            _capacity = newCapacity;
        }
        _pArray[_size] = tm;
        _size++;
    }
    void pop_back()
    {
        if (_size == 0)
        {
            cout << "Array is empty!" << endl;
            return;
        }
        _size--;
    }
    T operator[](const int &index) const
    {
        return _pArray[index];
    }
    int getSize() const
    {
        return _size;
    }
    int getCapacity() const
    {
        return _capacity;
    }
    bool isEmpty() const
    {
        return (_size == 0);
    }
    void showArray() const
    {
        for (size_t i = 0; i < _size; i++)
        {
            cout << _pArray[i] << "  ";
        }
        cout << endl;
    }
    ~myArray();

private:
    T *_pArray;
    int _capacity;
    int _size;
};
template <class T>
myArray<T>::myArray()
{
    _capacity = 0;
    _size = 0;
    _pArray = new T[_capacity];
}
template <class T>
myArray<T>::~myArray()
{
    if (_pArray != nullptr)
    {
        delete[] _pArray;
        _pArray = nullptr;
        _size = 0;
        _capacity = 0;
    }
}

// for test01 // int type
void printMyArray(const myArray<int> &Arr)
{
    bool empflag = Arr.isEmpty();
    cout << "empflag = " << empflag << endl;
    int size = Arr.getSize();
    cout << "size = " << Arr.getSize() << endl;
    int capacity = Arr.getCapacity();
    cout << "capacity = " << Arr.getCapacity() << endl;
    Arr.showArray();
    cout << "-----------------------------" << endl;
}
void test01()
{
    myArray<int> array;
    printMyArray(array);
    for (size_t i = 0; i < 21; i++)
    {
        array.push_back(i);
    }
    printMyArray(array);

    array.pop_back();
    array.pop_back();
    printMyArray(array);
    // // test array []
    // cout << array._pArray[20] << endl;
    // cout << array._pArray[290] << endl;
}

// for test02 // Person type
class Person
{
public:
    Person() {}
    Person(string name, int age)
    {
        this->m_Name = name;
        this->m_Age = age;
    }

public:
    string m_Name;
    int m_Age;
};
void printPersonArray(const myArray<Person> &personArr)
{
    for (int i = 0; i < personArr.getSize(); i++)
    {
        cout << "name: " << personArr[i].m_Name << "\t"
             << " age: " << personArr[i].m_Age << endl;
    }
}

void test02()
{
    myArray<Person> pArray(5);
    Person p1("jonny", 10);
    Person p2("kimi", 20);
    Person p3("lucky", 11);
    Person p4("sweet", 5);
    // Person p5("kubi", 18);

    pArray.push_back(p1);
    pArray.push_back(p2);
    pArray.push_back(p3);
    pArray.push_back(p4);
    // pArray.push_back(p5);

    printPersonArray(pArray);

    cout << "capacity = " << pArray.getCapacity() << endl;
    cout << "size = " << pArray.getSize() << endl;

    pArray.pop_back();
    pArray.pop_back();
    printPersonArray(pArray);

    cout << "capacity = " << pArray.getCapacity() << endl;
    cout << "size = " << pArray.getSize() << endl;
}

int main()
{
    test01();
    test02();
    return 1;
}